//md5 d6cdf44056d1e308eec721e4d178b0ab
(function() {
  var _, _expr, _importLib, all0, all1, bin, cat, chdl_base, dec, expand, fft, has0, has1, hasEven1, hasOdd1, hex, infer, oct;

  chdl_base = require('chdl_base');

  ({_expr} = require('chdl_utils'));

  ({cat, expand, all1, all0, has0, has1, hasOdd1, hasEven1} = require('chdl_operator'));

  ({infer, hex, oct, bin, dec} = require('chdl_base'));

  ({_importLib} = require('chdl_transpiler_engine'));

  module.paths.push('/home/lisiyu/work/project/fft/src');

  _ = require("lodash");

  fft = class fft extends chdl_base.Module {
    constructor(cell_num, addr_width, data_width) {
      super();
      this.cell_num = cell_num != null ? cell_num : 1;
      this.addr_width = addr_width != null ? addr_width : 32;
      this.data_width = data_width != null ? data_width : 64; // real + imag
      this.cal_step = 5;
      this.pri_lib = this._mixinas(_importLib('./private_lib.chdl', __dirname));
      
      //CellMap(name: new cell())
      this.instr_config = {
        instr_width: 16,
        addr_width: 32,
        op_code_bit_width: 4,
        cell_bit_width: 2,
        immed_bit_width: 10,
        cell_num: 1,
        ram_depth: 512
      };
      this._port({
        fft_cfg: {
          start: chdl_base.input()
        },
        sram: this.createArray(this.cell_num, () => {
          return {
            valid: chdl_base.output(),
            ready: chdl_base.input(),
            we_n: chdl_base.output(),
            addr: chdl_base.output(this.addr_width),
            wdata: chdl_base.output(this.data_width),
            rdata: chdl_base.input(this.data_width)
          };
        }),
        instr_sram: {
          valid: chdl_base.output(),
          ready: chdl_base.input(),
          we_n: chdl_base.output(),
          addr: chdl_base.output(this.addr_width),
          wdata: chdl_base.output(this.instr_config.instr_width),
          rdata: chdl_base.input(this.instr_config.instr_width)
        },
        exp_sram: {
          valid: chdl_base.output(),
          ready: chdl_base.input(),
          we_n: chdl_base.output(),
          addr: chdl_base.output(this.addr_width),
          wdata: chdl_base.output(this.data_width),
          rdata: chdl_base.input(this.data_width)
        }
      });
      this._wire();
      this._reg();
      this._channel();
    }

    build() {
      var cal_res, cell_idx, config, ctrl, decode_ctrl, en, exp, exp_sram_addr_list, exp_sram_cond_list, exp_sram_idx_list, exp_sram_ready_dly, fetch_instr_enable, fft_calc_grant, fft_ctrl, fft_end, grant, i, instr, j, k, l, len, len1, len2, len3, len4, len5, len6, len7, m, n, o, p, q, r, rd_signal, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, results, sram_list, wr_signal;
      config = {
        sign_bit: 31,
        exp_slice: {
          30: 23
        },
        exp_width: 8,
        factor_slice: {
          22: 0
        },
        factor_width: 23,
        width: 32
      };
      fft_ctrl = this.createArray(this.cell_num, () => {
        return {
          valid: this._localWire(1),
          ready: this._localWire(1),
          grant: this._localWire(1),
          even_addr: this._localWire(this.addr_width),
          odd_addr: this._localWire(this.addr_width),
          exp: this._localReg(this.data_width)
        };
      });
      rd_signal = this.createArray(this.cell_num, () => {
        return {
          valid: this._localWire(1, "rd_valid"),
          ready: this._localWire(1, "rd_ready"),
          grant: this._localWire(1, "rd_grant"),
          even_addr: this._localWire(this.addr_width, "rd_even_addr"),
          even_data: this._localReg(this.data_width, "rd_even_data"),
          odd_addr: this._localWire(this.addr_width, "rd_odd_addr"),
          odd_data: this._localWire(this.data_width, "rd_odd_data")
        };
      });
      wr_signal = this.createArray(this.cell_num, () => {
        return {
          valid: this._localWire(1, "wr_valid"),
          ready: this._localWire(1, "wr_ready"),
          grant: this._localWire(1, "wr_grant"),
          even_addr: this._localWire(this.addr_width, "wr_even_addr"),
          add_data: this._localWire(this.data_width, "wr_add_data"),
          odd_addr: this._localWire(this.addr_width, "wr_odd_addr"),
          sub_data: this._localReg(this.data_width, "wr_sub_data")
        };
      });
      
      //cal_res=@createArray(@cell_num, ()=>
      //    return {
      //      out_add : wire() 
      //    }

      //  )
      exp = this._localReg(this.data_width, "exp_data");
      fft_end = this._localWire(1, "fft_end");
      fetch_instr_enable = this._localWire(1, "fetch_instr_enable");
      sram_list = [];
      cal_res = [];
      ctrl = [];
      en = [];
      console.log("fft");
      instr = this.pri_lib.$instr_fetch(fetch_instr_enable, this.instr_sram, this.instr_config, this.fft_cfg.start, fft_end);
      grant = 1;
      ref = _.range(this.cell_num);
      for (k = 0, len = ref.length; k < len; k++) {
        i = ref[k];
        console.log(grant);
        //Net t = grant & fft_ctrl[i].grant
        //grant = t
        grant = _expr(chdl_base.Expr.start().next(grant).next("&").next(fft_ctrl[i].grant), '134');
      }
      fft_calc_grant = this._localWire(1, "fft_calc_grant");
      this._assign(fft_calc_grant, '136')(() => {
        return _expr(chdl_base.Expr.start().next(grant).next("&&").next("(").next("!").next(this.exp_sram.valid).next(")").next("|").next(this.exp_sram.ready), '136');
      });
      decode_ctrl = this.pri_lib.$instr_decode(instr, fft_calc_grant, this.instr_config, fft_end, fetch_instr_enable);
      ref1 = _.range(this.cell_num);
      for (l = 0, len1 = ref1.length; l < len1; l++) {
        i = ref1[l];
        ctrl[i] = this.pri_lib.$ctrl_pip(rd_signal[i].ready, wr_signal[i].grant, rd_signal[i].even_addr, rd_signal[i].odd_addr);
        ref2 = _.range(this.cal_step);
        for (m = 0, len2 = ref2.length; m < len2; m++) {
          j = ref2[m];
          en.push(ctrl[i][j].valid);
        }
        sram_list[i] = this.pri_lib.$mem_if(rd_signal[i], wr_signal[i], wr_signal[i].grant);
        cal_res[i] = this.pri_lib.$fft_cell(exp, rd_signal[i].even_data, rd_signal[i].odd_data, en, config);
      }
      ref3 = _.range(this.cell_num);
      for (n = 0, len3 = ref3.length; n < len3; n++) {
        i = ref3[n];
        this._assign(wr_signal[i].even_addr, '153')(() => {
          return _expr(chdl_base.Expr.start().next(ctrl[i][this.cal_step - 1].even_addr), '153');
        });
        this._assign(wr_signal[i].odd_addr, '154')(() => {
          return _expr(chdl_base.Expr.start().next(ctrl[i][this.cal_step - 1].odd_addr), '154');
        });
        this._assign(wr_signal[i].valid, '155')(() => {
          return _expr(chdl_base.Expr.start().next(ctrl[i][this.cal_step - 1].valid), '155');
        });
        this._assign(wr_signal[i].add_data, '156')(() => {
          return _expr(chdl_base.Expr.start().next(cal_res[i].out_add), '156');
        });
        this._assign(wr_signal[i].sub_data, '157')(() => {
          return _expr(chdl_base.Expr.start().next(cal_res[i].out_sub), '157');
        });
      }
      ref4 = _.range(this.cell_num);
      for (o = 0, len4 = ref4.length; o < len4; o++) {
        i = ref4[o];
        this._assign(rd_signal[i].even_addr, '160')(() => {
          return _expr(chdl_base.Expr.start().next(fft_ctrl[i].even_addr), '160');
        });
        this._assign(rd_signal[i].odd_addr, '161')(() => {
          return _expr(chdl_base.Expr.start().next(fft_ctrl[i].odd_addr), '161');
        });
        this._assign(rd_signal[i].valid, '162')(() => {
          return _expr(chdl_base.Expr.start().next(fft_ctrl[i].valid), '162');
        });
        this._assign(fft_ctrl[i].ready, '163')(() => {
          return _expr(chdl_base.Expr.start().next(rd_signal[i].ready), '163');
        });
        this._assign(fft_ctrl[i].grant, '164')(() => {
          return _expr(chdl_base.Expr.start().next(rd_signal[i].grant), '164');
        });
        this._assign(fft_ctrl[i].even_addr, '165')(() => {
          return _expr(chdl_base.Expr.start().next(decode_ctrl[i].even_addr), '165');
        });
        this._assign(fft_ctrl[i].odd_addr, '166')(() => {
          return _expr(chdl_base.Expr.start().next(decode_ctrl[i].odd_addr), '166');
        });
        this._assign(fft_ctrl[i].valid, '167')(() => {
          return _expr(chdl_base.Expr.start().next(decode_ctrl[i].valid), '167');
        });
      }
      ref5 = _.range(this.cell_num);
      for (p = 0, len5 = ref5.length; p < len5; p++) {
        i = ref5[p];
        this._assign(this.sram[i].valid, '170')(() => {
          return _expr(chdl_base.Expr.start().next(sram_list[i].valid), '170');
        });
        this._assign(this.sram[i].we_n, '171')(() => {
          return _expr(chdl_base.Expr.start().next(sram_list[i].we_n), '171');
        });
        this._assign(this.sram[i].addr, '172')(() => {
          return _expr(chdl_base.Expr.start().next(sram_list[i].addr), '172');
        });
        this._assign(this.sram[i].wdata, '173')(() => {
          return _expr(chdl_base.Expr.start().next(sram_list[i].wdata), '173');
        });
        this._assign(sram_list[i].ready, '174')(() => {
          return _expr(chdl_base.Expr.start().next(this.sram[i].ready), '174');
        });
        this._assign(sram_list[i].rdata, '175')(() => {
          return _expr(chdl_base.Expr.start().next(this.sram[i].rdata), '175');
        });
      }
      exp_sram_cond_list = [];
      exp_sram_addr_list = [];
      exp_sram_idx_list = [];
      cell_idx = this._localReg(4, "cell_idx");
      ref6 = _.range(this.cell_num);
      for (q = 0, len6 = ref6.length; q < len6; q++) {
        i = ref6[q];
        console.log("list");
        exp_sram_cond_list.push(this._cond(chdl_base.Expr.start().next(decode_ctrl[i].valid), '185')(() => {
          return _expr(chdl_base.Expr.start().next(bin(1, 1)), '185');
        }));
        exp_sram_addr_list.push(this._cond(chdl_base.Expr.start().next(decode_ctrl[i].valid), '186')(() => {
          return _expr(chdl_base.Expr.start().next(decode_ctrl[i].exp_addr), '186');
        }));
        exp_sram_idx_list.push(this._cond(chdl_base.Expr.start().next(decode_ctrl[i].valid), '187')(() => {
          return _expr(chdl_base.Expr.start().next(i), '187');
        }));
      }
      exp_sram_cond_list.push(this._cond(chdl_base.Expr.start().next("null"), '189')(() => {
        return _expr(chdl_base.Expr.start().next(dec(0)), '189');
      }));
      exp_sram_addr_list.push(this._cond(chdl_base.Expr.start().next("null"), '190')(() => {
        return _expr(chdl_base.Expr.start().next(dec(0)), '190');
      }));
      exp_sram_idx_list.push(this._cond(chdl_base.Expr.start().next("null"), '191')(() => {
        return _expr(chdl_base.Expr.start().next(this.cell_num), '191');
      }));
      this._assign(cell_idx, '194')(() => {
        return _expr(chdl_base.Expr.start().next(this._order(exp_sram_idx_list)), '194');
      });
      this._assign(this.exp_sram.valid, '195')(() => {
        return _expr(chdl_base.Expr.start().next(this._order(exp_sram_cond_list)), '195');
      });
      this._assign(this.exp_sram.addr, '196')(() => {
        return _expr(chdl_base.Expr.start().next(this._order(exp_sram_addr_list)), '196');
      });
      this._assign(this.exp_sram.we_n, '197')(() => {
        return _expr(chdl_base.Expr.start().next(dec(1)), '197');
      });
      exp_sram_ready_dly = this._localReg(1, "exp_sram_dly");
      this._assign(exp_sram_ready_dly, '200')(() => {
        return _expr(chdl_base.Expr.start().next(this.exp_sram.ready), '200');
      });
      ref7 = _.range(this.cell_num);
      results = [];
      for (r = 0, len7 = ref7.length; r < len7; r++) {
        i = ref7[r];
        console.log("x");
        results.push(this._assign(fft_ctrl[i].exp, '203')(() => {
          return this._if(chdl_base.Expr.start().next(exp_sram_ready_dly).next("&&").next(cell_idx).next("==").next(i), '204')(() => {
            return _expr(chdl_base.Expr.start().next(this.exp_sram.rdata), '205');
          })._else('206')(() => {
            return _expr(chdl_base.Expr.start().next(fft_ctrl[i].exp), '207');
          })._endif();
        }));
      }
      return results;
    }

  };

  module.exports = fft;

  return module.exports;

}).call(this);
